from dataclasses import dataclass, field
from datetime import datetime
from typing import List,Tuple,Dict
from nicegui import binding
from utils import parse_datetime
from grouperdb import GrouperDB
from drg_group.chs_drg_11.Base import GroupResult
from enums import OptionEnums
# from base import DRGCaculato


@dataclass
class QueryData:
    patient_number: str=binding.BindableProperty()
    patient_name: str=binding.BindableProperty()
    department: str=binding.BindableProperty()
    start_date: str=binding.BindableProperty()
    end_date: str=binding.BindableProperty()
    leaving_type: int =binding.BindableProperty() 
    doctor_name: str =binding.BindableProperty()

    def __init__(self, patient_number: str='', patient_name: str='', department: str='', start_date: str='', end_date: str='', leaving_type: int =1, doctor_name: str ='') -> None:
        self.patient_number = patient_number
        self.patient_name = patient_name
        self.department = department
        self.start_date = start_date
        self.end_date = end_date
        self.leaving_type = leaving_type
        self.doctor_name = doctor_name

    def to_string(self) -> str:
        if self.patient_number:
            return f'bah="{self.patient_number}"'
        str='1=1 '
        if self.patient_name:
            str+=f' and xm Like "%{self.patient_name}%" '
        if self.department:
            str+=f' and cybf={self.department} '
        if self.start_date and self.end_date:
            if parse_datetime(self.start_date) and parse_datetime(self.end_date):
                str+=f' and cysj>={int(parse_datetime(self.start_date).strftime("%Y%m%d"))} and cysj<={int(parse_datetime(self.end_date).strftime("%Y%m%d"))}'
        return str


@dataclass
class MedicalRecord:
    '''
    MedicalRecord存储从数据库查询的病案首页的基本信息、入院时间、出院时间、科室、病历号、诊断、手术等信息
    两个主要用途：1、 与web ui进行数据交互，实现页面的动态更新；2、将病例信息格式化为分组组接受的格式
    '''
    patient_number: str=binding.BindableProperty()
    patient_name: str=binding.BindableProperty()
    _patient_gender: str=binding.BindableProperty()
    _patient_age: int=binding.BindableProperty()
    department: str=binding.BindableProperty()
    admission_date: datetime=binding.BindableProperty()
    discharge_date: datetime=binding.BindableProperty()
    _days: int=binding.BindableProperty()
    _patient_amount: float=binding.BindableProperty()
    _leaving_type: int =binding.BindableProperty() 
    diseases:List=binding.BindableProperty()
    surgerys:List=binding.BindableProperty()

    def __init__(self, patient_number: str='', patient_name: str='', patient_gender: int='', patient_age: int='', department: str='', admission_date: str='', discharge_date: str='', leaving_type: int =1,patient_amount: float=0.0, diseases:List=[], surgerys:List=[]) -> None:
        self.patient_number = patient_number
        self.patient_name = patient_name
        try:    
            self._patient_gender = int(patient_gender)
        except:
            self._patient_gender = 1

        try:
            self._patient_age = int(patient_age)
        except:
            self._patient_age = 0
        self.department = department
        self.admission_date = admission_date       # %Y-%m-%d %H:%M:%S
        self.discharge_date = discharge_date       # %Y-%m-%d %H:%M:%S
        try:
            self._leaving_type = int(leaving_type)
        except:
            self._leaving_type = 1
        try:
            self._patient_amount = float(patient_amount)
        except:
            self._patient_amount = 0.0
        self.diseases = diseases
        self.surgerys = surgerys

    def __post_init__(self):
        self._days =max(1,  (self.discharge_date - self.admission_date).days)

    def from_dict(self, data: dict):
        self.patient_number = data.get('bah', '')
        self.patient_name = data.get('xm', '')
        self.patient_gender = data.get('xb', '')
        self.patient_age = data.get('nl', '')
        self.department = data.get('cybf', '')
        dt=parse_datetime(data.get('rysj', ''))
        if dt:
            self.admission_date = dt.strftime('%Y-%m-%d')
        else:
            self.admission_date = ''

        dt=parse_datetime(data.get('cysj', ''))
        if dt:
            self.discharge_date = dt.strftime('%Y-%m-%d')
        else:
            self.discharge_date = ''

        self.leaving_type = data.get('leaving_type', 1)
        self.patient_amount = data.get('amount', 0.0)
        self._days =max(1, (datetime.strptime(self.discharge_date, '%Y-%m-%d') - datetime.strptime(self.admission_date, '%Y-%m-%d')).days)

    def to_string(self) -> str:
        '''
        将病历信息格式化为分组器接受的格式
        '''
        diseases=','.join([str(d).strip() for d in self.diseases])
        surgerys=','.join([str(d).strip() for d in self.surgerys])        
        formated_str=f'{self.patient_number},{self.patient_gender},{self.patient_age},,,{self.department},{self.admission_date},{self.leaving_type},"{diseases}","{surgerys}"'
        return formated_str

    @property
    def days(self):
        return self._days

    @days.setter
    def days(self, value):
        try:
            value=int(value)
        except:
            value=0
        self._days = value

    @property
    def patient_age(self):
        return self._patient_age

    @patient_age.setter
    def patient_age(self, value):
        try:
            value=int(value)
        except:
            value=0
        self._patient_age = value

    @property
    def patient_amount(self):
        return self._patient_amount

    @patient_amount.setter
    def patient_amount(self, value):
        try:
            value=float(value)
        except:
            value=0.0
        self._patient_amount = value

    @property
    def leaving_type(self):
        return self._leaving_type

    @leaving_type.setter
    def leaving_type(self, value):
        try:
            value=int(value)
        except:
            value=1
        self._leaving_type = value

    @property
    def patient_gender(self):
        return self._patient_gender

    @patient_gender.setter
    def patient_gender(self, value):
        try:
            value=int(value)
        except:
            value=1
        self._patient_gender = value


@dataclass
class DRGRecord:
    group_result:GroupResult=None
    medical_record:MedicalRecord=None
    drgs_code:str=''
    drgs_name:str=''
    drgs_weights:float=0.0                                     #病组权重（基础点数）
    drgs_ratio:float=0.0                                       #等级系数
    drgs_average:float=0.0                                     #病组例均费用
    drg_type:str=''                                            #病组类型,住院超61天、低倍率病例……
    main_average:float=OptionEnums.MAIN_AVERAGE.value          # 统筹区域例均费用
    resident_price:float=OptionEnums.RESIDENT_PRICE.value      # 居民医保点值
    employees_price:float=OptionEnums.EMPLOYEES_PRICE.value     # 职工医保点值
    patient_weights:float=0.0                                  # 病例权重（病例点数）
    patient_amount:float=0.0                                   # 病例费用
    drg_amount=None           # drg病例费用，含自费部分

    def from_drg_caculator(self,drg_caculator)->None:
        self.drgs_code=drg_caculator.drgs_code
        self.drgs_name=drg_caculator.drgs_name
        self.drgs_weights=drg_caculator.drgs_weights
        self.drgs_ratio=drg_caculator.drgs_ratio
        self.drgs_average=drg_caculator.drgs_average
        self.drg_type=drg_caculator.drg_type
        self.main_average=drg_caculator.main_average
        self.resident_price=drg_caculator.resident_price
        self.employees_price=drg_caculator.employees_price
        self.patient_weights=drg_caculator.patient_weights
        self.patient_amount=drg_caculator.patient_amount
        self.drg_amount=drg_caculator.drg_amount

    # def __init__(self,group_result:GroupResult,medical_record:MedicalRecord):
    #     self.group_result=group_result 
    #     self.medical_record=medical_record       
        

    # def get_drgs_info(self):
    #     drgs=GrouperDB().query_drgs_one(self.group_result.drg)        
    #     if not drgs:
    #         return None
    #     self.drgs_code=drgs['CODE']
    #     self.drgs_name=drgs['NAME']
    #     self.drgs_weights=drgs['WEIGHTS']
    #     self.drgs_ratio=drgs['RATIO']
    #     self.drgs_average=drgs['AVERAGE']


    # def is_higher(self)->Tuple[bool,float]:
    #     if self.medical_record.patient_amount<=self.drgs_average*1.3:
    #         return (False,0)
        
    #     if self.drgs_weights<=100:
    #         if self.medical_record.patient_amount>self.drgs_average*2.5:
    #             return (True,2.5)
    #         else:
    #             return (False,0)            
        
    #     elif self.drgs_weights<=200:
    #         if self.medical_record.patient_amount>self.drgs_average*2:
    #             return (True,2)
    #         else:
    #             return (False,0)
            
    #     elif self.drgs_weights<=500:
    #         if self.medical_record.patient_amount>self.drgs_average*1.5:
    #             return (True,1.5)
    #         else:
    #             return (False,0)
            
    #     else:
    #         if self.medical_record.patient_amount>self.drgs_average*1.3:
    #             return (True,1.3)
    #     return (False,0)

    # def is_lower(self)->bool:
    #      if self.medical_record.patient_amount<self.drgs_average*0.4:
    #             return True
    #      return False


    # def calculate_drg_amount(self):        
    #     if self.medical_record.days>=61:
    #         self.patient_weights=self.medical_record.patient_amount/self.main_average*100
    #     else:
    #         is_higher,multiplier =self.is_higher()
    #         if is_higher:
    #             self.patient_weights=self.drgs_weights*self.drgs_ratio+(self.medical_record.patient_amount/self.drgs_average-multiplier)*self.drgs_weights
    #         elif self.is_lower():
    #             self.patient_weights=self.medical_record.patient_amount/self.drgs_average*self.drgs_weights*self.drgs_ratio
    #             self.patient_weights=min(self.patient_weights,self.drgs_weights*self.drgs_ratio*0.4)
    #         else:
    #             if self.medical_record.leaving_type==2 or self.medical_record.leaving_type==4 or self.medical_record.leaving_type==5 or self.medical_record.leaving_type==9:
    #                 self.patient_weights=self.drgs_weights*self.drgs_ratio*(self.medical_record.patient_amount/self.drgs_average)
    #             else:
    #                 self.patient_weights=self.drgs_weights*self.drgs_ratio

    #     self.drg_amount['resident']=self.patient_weights*self.resident_price
    #     self.drg_amount['emplyees']=self.patient_weights*self.employees_price
    
    # def drg_computed(self):
    #     self.get_drgs_info()
    #     if not self.drgs_code:
    #         return None        
    #     self.calculate_drg_amount()
    #     return self


        
        
